import { computed, ref, watch, shallowRef, type ComputedRef } from "vue";

/**
 * 性能优化的响应式计算Hook
 * 提供缓存、防抖、浅层响应式等优化功能
 */

// 计算结果缓存
const computedCache = new Map<string, any>();

/**
 * 带缓存的计算属性
 * @param fn 计算函数
 * @param key 缓存键
 * @param deps 依赖项数组
 */
export function useCachedComputed<T>(
  fn: () => T,
  key: string,
  deps: any[] = []
): ComputedRef<T> {
  return computed(() => {
    // 生成依赖键
    const depKey = `${key}:${deps.map(d => JSON.stringify(d)).join(",")}`;

    // 检查缓存
    if (computedCache.has(depKey)) {
      return computedCache.get(depKey);
    }

    // 计算新值
    const result = fn();

    // 缓存结果
    computedCache.set(depKey, result);

    return result;
  });
}

/**
 * 清除计算缓存
 * @param key 缓存键（可选，不传则清除所有）
 */
export function clearComputedCache(key?: string) {
  if (key) {
    // 清除特定键的缓存
    for (const [cacheKey] of computedCache) {
      if (cacheKey.startsWith(key)) {
        computedCache.delete(cacheKey);
      }
    }
  } else {
    // 清除所有缓存
    computedCache.clear();
  }
}

/**
 * 防抖响应式值
 * @param value 响应式值
 * @param delay 防抖延迟
 */
export function useDebouncedRef<T>(value: T, delay: number = 300) {
  const debouncedValue = ref(value);
  const originalRef = ref(value);

  let timeout: number;

  watch(
    () => originalRef.value,
    newValue => {
      clearTimeout(timeout);
      timeout = window.setTimeout(() => {
        debouncedValue.value = newValue as any;
      }, delay);
    },
    { immediate: true }
  );

  return {
    value: debouncedValue,
    setValue: (newValue: T) => {
      originalRef.value = newValue as any;
    },
  };
}

/**
 * 浅层响应式引用，提升性能
 */
export function useShallowReactiveRef<T extends object>(initialValue: T) {
  return shallowRef(initialValue);
}

/**
 * 批量更新优化
 */
export function useBatchUpdate() {
  const updateQueue = ref<(() => void)[]>([]);
  let isFlushPending = false;

  const addUpdate = (update: () => void) => {
    updateQueue.value.push(update);

    if (!isFlushPending) {
      isFlushPending = true;
      requestAnimationFrame(() => {
        // 批量执行更新
        const updates = updateQueue.value.slice();
        updateQueue.value = [];
        isFlushPending = false;

        updates.forEach(update => update());
      });
    }
  };

  return { addUpdate };
}
